home *** CD-ROM | disk | FTP | other *** search
- #include "BuildControl.h"
-
-
-
- #if defined(qUseDumpFile)
- #include "DumpHeader.h"
- #else
- #include <Resources.h>
- #endif
-
- #include "DragSupport.h"
-
- DragHandlerGlobals pDragGlobals;
-
- //-----------------------------------------------------------------------
-
- Boolean DragMgrPresent(void)
- {
- OSErr err;
- long response = 0L;
-
- err = Gestalt(gestaltDragMgrAttr, &response);
-
- if ((err == noErr)
- && (response && (1 << gestaltDragMgrPresent) != 0))
- return true;
-
- else
- return false;
- }
-
- //-----------------------------------------------------------------------
- // InstallDragHandlers attaches my tracking and receive handlers to
- // one of the application's windows
- //-----------------------------------------------------------------------
- OSErr InstallDragHandlers(WindowPtr win)
- {
- OSErr err;
-
- if (DragMgrPresent()) {
- err = InstallTrackingHandler((DragTrackingHandler) DragTracker, win, nil);
- if (err != noErr) goto Bail;
-
- err = InstallReceiveHandler((DragReceiveHandler) DragReceiver, win, nil);
- if (err != noErr)
- (void) RemoveTrackingHandler((DragTrackingHandler) DragTracker, win);
- }
-
- Bail:
- return err;
- }
-
- //-----------------------------------------------------------------------
- // RemoveDragHandlers removes my tracking and receive handlers from
- // one of the application's windows (prior to the window's disposal,
- // presumably)
- //-----------------------------------------------------------------------
- void RemoveDragHandlers(WindowPtr win)
- {
- if (DragMgrPresent()) {
- RemoveReceiveHandler((DragReceiveHandler) DragReceiver, win);
- RemoveTrackingHandler((DragTrackingHandler) DragTracker, win);
- }
- }
-
- //-----------------------------------------------------------------------
- // DragItemsAreAcceptable returns true if the contents (data) of
- // the drag is only a 'TEXT' flavor.
- //
- // DragItemsAreAcceptable is called by the tracking and receive handlers
- //-----------------------------------------------------------------------
- Boolean DragItemsAreAcceptable(DragReference drag)
- {
- OSErr err;
- unsigned short totalItems;
- ItemReference itemRef;
- Boolean acceptIt;
- Ptr textFlavor;
- Size dataSize;
-
- acceptIt = false;
- err = CountDragItems(drag, &totalItems);
-
- if ((err == noErr) && (totalItems == 1)) {
- //
- // Only accept the drag if there's only one flavor, and
- // its a TEXT one.
- //
- err = GetDragItemReferenceNumber(drag, 1, &itemRef);
- if (err != noErr) goto Bail;
-
- err = GetFlavorDataSize(drag, 1, 'TEXT', &dataSize);
- if (err != noErr) goto Bail;
-
- textFlavor = NewPtr(dataSize);
- if (textFlavor == NULL) goto Bail;
-
- err = GetFlavorData(drag, itemRef, 'TEXT', textFlavor, &dataSize, 0);
- if (err == noErr) acceptIt = true;
-
- DisposePtr(textFlavor);
- }
-
- Bail:
- return acceptIt;
- }
-
- //-----------------------------------------------------------------------
- // DragIsNotInSourceWindow returns true if the drag in progress
- // is not in the same window it originated in
- //
- // DragIsNotInSourceWindow is called by the tracking and receive handlers
- //
- // Note that, if this application allowed items to be dragged within
- // its windows, this function would not be appropriate.
- // Instead, hilighting would probably occur in the source window
- // when the dragHasLeftSourceWindow flag is set, and the receive
- // handler wouldn't check this at all
- //-----------------------------------------------------------------------
- Boolean DragIsNotInSourceWindow(DragReference drag)
- {
- DragAttributes currDragFlags;
-
- (void) GetDragAttributes(drag, &currDragFlags);
- return ((currDragFlags & dragInsideSenderWindow) == 0);
- }
-
- //-----------------------------------------------------------------------
- // DragTracker is called by the drag manager whenever a drag is
- // over one of the application's windows
- //
- // upon entry, the current port has been set to win by the Drag Manager
- //-----------------------------------------------------------------------
- pascal OSErr DragTracker(DragTrackingMessage message, WindowPtr win,
- void *handlerRefCon, DragReference drag)
- {
- #pragma unused (handlerRefCon)
- RgnHandle tempRgn;
- Rect rct, emptyRect = {0,0,0,0};
- OSErr err = noErr;
-
- switch (message) {
- case dragTrackingEnterHandler:
- //
- // Determine if the items are acceptable and store that
- // flag in the globals, plus reset the hilighted global flag
- //
- pDragGlobals.acceptableDragFlag = DragItemsAreAcceptable(drag);
- pDragGlobals.currDragRect = emptyRect;
- if (!pDragGlobals.acceptableDragFlag)
- err = dragNotAcceptedErr;
- break;
-
- case dragTrackingEnterWindow:
- case dragTrackingInWindow:
- case dragTrackingLeaveWindow:
-
- // Highlighting of the window during a drag is done
- // here. Do it only if we can accept these items
- // and we're not in the source window...
- if (pDragGlobals.acceptableDragFlag && DragIsNotInSourceWindow(drag)) {
- //
- // Unless the mouse is leaving the visible area of the
- // window, check if it's in the window's content region
- //
- if (message == dragTrackingLeaveWindow)
- rct = emptyRect;
- else
- rct = win->portRect;
-
- //
- // If the mouse is in the content area and the window
- // is not yet hilighted, then do the hilighting
- //
- if (!EmptyRect(&rct)
- && !EqualRect(&pDragGlobals.currDragRect, &rct)) {
- ClipRect(&win->portRect);
- tempRgn = NewRgn();
- RectRgn(tempRgn, &rct);
-
- if (ShowDragHilite(drag, tempRgn, true) == noErr)
- //
- // Remember that hilighting is now on
- //
- pDragGlobals.currDragRect = rct;
-
- DisposeRgn(tempRgn);
- }
- //
- // Else if the mouse is not in the content region
- // and the window is hilighted, erase the hilight
- //
- else if (EmptyRect(&rct)
- && !EqualRect(&pDragGlobals.currDragRect, &emptyRect)) {
- ClipRect(&win->portRect);
-
- if (HideDragHilite(drag) == noErr)
- //
- // Remember that hilighting is now off
- //
- pDragGlobals.currDragRect = emptyRect;
- }
- }
- break;
-
- case dragTrackingLeaveHandler:
- break;
-
- default:
- err = paramErr;
- }
-
- return err;
- }
-
- //-----------------------------------------------------------------------
- // DragReceiver is called by the drag manager whenever a drag is
- // ends on one of the application's windows
- //-----------------------------------------------------------------------
- pascal OSErr DragReceiver(WindowPtr win, void *handlerRefCon,
- DragReference drag)
- {
- #pragma unused (handlerRefCon, win)
- ItemReference itemRef;
- Size dataSize;
- Ptr textFlavor;
- OSErr err = noErr;
- unsigned short numItems, counter;
-
- if (!DragItemsAreAcceptable(drag) || !DragIsNotInSourceWindow(drag))
- return dragNotAcceptedErr;
-
- CountDragItems(drag, &numItems);
-
- for (counter = 1; counter <= numItems; counter++) {
- err = GetDragItemReferenceNumber(drag, counter, &itemRef);
- if (err != noErr) goto BailOut;
-
- err = GetFlavorDataSize(drag, itemRef, 'TEXT', &dataSize);
- if (err != noErr) goto BailOut;
-
- textFlavor = NewPtr(dataSize);
- if (textFlavor == NULL) goto BailOut;
-
- err = GetFlavorData(drag, itemRef, 'TEXT', textFlavor, &dataSize, 0);
- if (err == noErr) {
- //
- // The drag was successful. Do whatever you want with the data.
- //
- SysBeep(20);
- DisposePtr(textFlavor);
- }
- }
-
- BailOut:
- return err;
- }
-
- //-----------------------------------------------------------------------
- // OutlineRegion changes a region into a tracing of its border
- // which is appropriate for normal dragging
- //-----------------------------------------------------------------------
- void OutlineRegion(RgnHandle theRgn)
- {
- RgnHandle tempRgn;
-
- tempRgn = NewRgn();
- CopyRgn(theRgn, tempRgn);
- InsetRgn(tempRgn, 1, 1);
- DiffRgn(theRgn, tempRgn, theRgn);
- DisposeRgn(tempRgn);
- }
-
- //-----------------------------------------------------------------------
-
- OSErr AddTextFlavor(DragReference drag, ItemReference item, StringPtr str)
- {
- return AddDragItemFlavor(drag, item, 'TEXT', &str[1], str[0], 0);
- }
-
- //-----------------------------------------------------------------------
-
- OSErr StartDrag(WindowPtr win, EventRecord *event)
- {
- OSErr err;
- DragReference drag;
- Rect dragBounds;
- RgnHandle dragRgn;
- ItemReference item = 1;
-
- err = NewDrag(&drag);
- if (err != noErr) goto Bail;
-
- err = AddTextFlavor(drag, item, "\pInitial Add");
- if (err != noErr) goto DisposeDragAndBail;
-
- //
- // Generate the bounds and region for the drag using the window's
- // content rectangle
- //
- dragBounds = (**((WindowPeek) win)->contRgn).rgnBBox;
- err = SetDragItemBounds(drag, item, &dragBounds);
- if (err != noErr) goto DisposeDragAndBail;
-
- dragRgn = NewRgn();
- RectRgn(dragRgn, &dragBounds);
- OutlineRegion(dragRgn);
- err = TrackDrag(drag, event, dragRgn);
- DisposeRgn(dragRgn);
-
- DisposeDragAndBail:
- DisposeDrag(drag);
-
- Bail:
- return err;
- }
-